package entity.lemming;

import java.awt.Point;

import entity.Entity;
import entity.Sprite;
import entity.terrain.Terrain;
import level.*;

/**
 * A representation of a genaric Lemming entity
 * 
 * @author Neil Cowzer, Olga Murdoch
 */
public abstract class Lemming extends Sprite {
	
	/** The status of the lemmings health.*/
	protected boolean alive;
	
	/** true if lemming has reached goal.*/
	protected boolean saved;
	/*@ invariant alive == true && saved == true ||
	  			  alive == false && saved == false ||
	  			  alive == true && saved == false;
	 @*/
	
	/**true if lemming is in free fall*/
	protected boolean fall;
	
	/** true if lemming is enter crushed animation */
	protected boolean crush;
	
	/** The energy level of the lemming.*/
	protected int energy;
	/*@ invariant 0 <= energy &&
					   energy <= 100;
	@*/
	
	/** The current speed of the lemming in the x-plane. */
	protected int speed_X;

	/** The current speed of the lemming in the y-plane. */
	protected int speed_Y;
	
	/**True if lemming collides false otherwise*/
	protected boolean collide;

	/** The old speed of the lemming in the x-plane. */
	protected int old_speed_X = 0;

	/** The old speed of the lemming in the y-plane. */
	protected int old_speed_Y = 0;

	/** the last type of the lemming */
	protected String lasttype;
	
	/**
	 * Create a new Lemming.
	 * 
	 * @param level The level which the Lemming exist in.
	 * @param ref The sprite which should be displayed.
	 * @param x The x-coordinate of the Lemming.
	 * @param y The y-coordinate of the Lemming.
	 */
	/*@ requires ref != null && 0 <= x && 0 <= y && level != null;
	   	assignable level;
	   	ensures true;
	 */
	public Lemming(String ref, int numImages, int x,int y) {
		super(ref, numImages, x, y);
		// bring the lemming to life
		alive = true;
		saved = false;
		fall = false;
		collide = false;
	}
	
	/**
	 * Create a new lemming whose "center" will be the same as the center arguement
	 * 
	 * @param location of images
	 * @param number of animations
	 * @param the "center" point of the lemming
	 */
	public Lemming(String ref, int numImages, Point center){
		super(ref, numImages, center.x, center.y);
		
		// adjust the coordinates to tha appropiate value
		x = x - img.getWidth()/2;
		y = y - img.getHeight();
		
		alive = true;
		saved = false;
		fall = false;
		collide = false;
	}
	
	/**
	 * get the last type of lemming
	 * 
	 * @param the type of lemming
	 */
	public String getLastType(){
		return lasttype;
	}
	
	
	/** Request that this lemming perform the appropiate action/movement. */ 
	public abstract void move(Terrain terrain);
	
	/** Kill the current lemming */
	//@ ensures alive == false;
	public void kill(){
		alive = false;
	}
	
	/** Get the center of the lemming. */
	public Point center(){
		return new Point(getX() + img.getWidth()/2, getY() + img.getHeight());
	}
	
	/** Reverse a Lemmings direction */
	public abstract void turnAround();
	
	/**
	 * Check if this Lemming should enter free-fall.
	 * 
	 * @return True if the Lemming should free-fall
	 */
	public boolean fall(){
		// if there is no ground beneatbh the lemming enter free-fall
		// else
		
		return fall;
	}
	
	/**
	 * Check if the Lemming is alive
	 * 
	 * @return True if Lemming is alive
	 */
	public /*@ pure @*/ boolean isAlive(){
		return alive;
	}
	
	/**
	 * Check if the lemming is to be crushed.
	 * 
	 * @return true if the lemming is to be crushed
	 */
	public /*@ pure @*/ boolean crush(){
		return crush;
	}
	
	/**
	 * Retrieve the Lemmings speed in the x-plane
	 * 
	 * @return the integer value of the speed
	 */
	public /*@ pure @*/ int energy(){
		return energy;
	}
	
	/**
	 * Check is the lemming saved
	 * 
	 * @return a true if the lemming has been saved
	 */
	public /*@ pure @*/ boolean saved(){
		return saved;
	}
	
	/**
	 * Check if the lemming collides
	 * 
	 * @return a true if the lemming has been saved
	 */
	public /*@ pure @*/ boolean collide(){
		return collide;
	}
	
	/**
	 * Retrieve the Lemmings speed in the x-plane
	 * 
	 * @return the integer value of the speed
	 */
	public /*@ pure @*/ int getSpeed_X(){
		return speed_X;
	}
	
	/**
	 * Retrieve the Lemmings speed in the y-plane
	 * 
	 * @return the integer value of the speed
	 */
	public /*@ pure @*/ int getSpeed_Y(){
		return speed_Y;
	}
	
	/**
	 * Store the "old" speed.
	 * 
	 * @param values of last speed
	 */
	public void setOldSpeed(int x, int y){
		old_speed_Y = y;
		old_speed_X = x;
	}
	
	/**
	 * Retrieve the Lemmings old speed in the x-plane
	 * 
	 * @return the integer value of the speed
	 */
	public /*@ pure @*/ int getOldSpeed_X(){
		return old_speed_X;
	}
	
	/**
	 * Retrieve the Lemmings old speed in the y-plane
	 * 
	 * @return the integer value of the speed
	 */
	public /*@ pure @*/ int getOldSpeed_Y(){
		return old_speed_Y;
	}
	
	/**
	 * Check to see if a Lemming collides with another entity
	 * 
	 * @param other another entity eg. terrain, blocker.
	 * @return True if Lemming collides with another
	 */
	public abstract boolean collision(Lemming other);
}
